ECON 494 - Spatial Data Science Project

Our project aimed to analyze the Ukraine conflict using spatial analysis and maps generated through data from ACLED (Armed Conflict Location & Event Data Project). Focusing on the violence targeting civilians after invasion of Russia into Ukraine, we utilized R programming to extract and visualize the conflict data, enabling us to present a comprehensive overview of the events and their spatial distribution.

library(sp)
library(raster)
library(ggplot2)
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:raster’:

    intersect, select, union

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(tidyverse)
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ lubridate 1.9.2     ✔ tibble    3.2.1
✔ purrr     1.0.1     ✔ tidyr     1.3.0
✔ readr     2.1.4     ── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::extract() masks raster::extract()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
✖ dplyr::select()  masks raster::select()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(conflicted)

Introduction

  • Russia invaded Ukraine in February 2022, resulting in the highest levels of political violence recorded in a single country by ACLED.

  • Civilians in Ukraine have faced shelling, indiscriminate strikes, deliberate attacks, and harsh treatment in occupied areas.

  • Russian forces targeted Kyiv but retreated in northern Ukraine while quickly seizing territories in southern and eastern regions.

  • Over 5,000 reported civilian fatalities have occurred, but the actual toll is likely much higher.

  • Different regions of Ukraine experienced varying levels of violence and occupation during the conflict.

#ukraine_states_rds <- raster::getData('GADM', country = "UKR", level = 1)
ukraine_states_rds = readRDS("ukraine.rds") #https://gadm.org/download_country.html
ukraine_map <- ggplot() +
  geom_polygon(data=ukraine_states_rds,  aes(x = long, y = lat, group = group, fill = id), fill="orange", alpha = 0.6 ) + guides(fill = "none")
Regions defined for each Polygons
ukraine_map

east_ukraine_states_rds_names <- list("Dnipropetrovs'k", "Donets'k", "Luhans'k" ,  "Kharkiv", "Zaporizhzhya")

east_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% east_ukraine_states_rds_names)
south_ukraine_states_rds_names <- list("Chernihiv", "Kiev", "Kiev City", "Zhytomyr", "Sumy")
south_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% south_ukraine_states_rds_names)
central_ukraine_states_rds_names <- list("Cherkasy", "Kirovohrad", "Poltava", "Vinnytsya")
central_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% central_ukraine_states_rds_names)
western_ukraine_states_rds_names <- list("Volyn", "Chernivtsi", "Ivano-Frankivs'k", "Khmel'nyts'kyy", "Rivne", "L'viv", "Ternopil'", "Transcarpathia")
western_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% western_ukraine_states_rds_names)
southern_ukraine_states_rds_names <- list("Crimea", "Kherson",  "Mykolayiv", "Odessa")
southern_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% southern_ukraine_states_rds_names)
ukraine_map2 <- ukraine_map + 
  geom_polygon(data=east_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="red", alpha=0.2, color="black") +
  geom_polygon(data=south_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="black", alpha=0.2, color="black") +
  geom_polygon(data=central_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="darkblue", alpha=0.4, color="black") +
  geom_polygon(data=western_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="lightblue", alpha=0.2, color="black") +
  geom_polygon(data=southern_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black")
Regions defined for each PolygonsRegions defined for each PolygonsRegions defined for each PolygonsRegions defined for each PolygonsRegions defined for each Polygons
ukraine_map2

centroid <- ukraine_states_rds$centroid <- coordinates(ukraine_states_rds)
ukraine_states_rds_names <- ukraine_states_rds$NAME_1
ukraine_map3 <- ukraine_map2 + 
  geom_text(aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds_names), size=2) + labs(title = "Regions of Ukraine", fontface="bold") + theme_void() + theme(plot.title = element_text(hjust = 0.5, face = "bold")) +  coord_map(projection = "albers", lat0 = 49, lat1 = 54)
ukraine_map3

Conflict Data (ACLED)

eastern_ukraine_states_names = list("Dnipropetrovsk", "Luhansk", "Donetsk", "Kharkiv", "Zaporizhia")
conflict <- read_csv('ukraine.csv', show_col_types = FALSE)
conflict$event_date <- as.Date(conflict$event_date, format = "%d %B %Y")
unique(conflict$admin1)
 [1] "Dnipropetrovsk"  "Luhansk"         "Donetsk"         "Kharkiv"         "Kherson"         "Sumy"            "Zaporizhia"      "Kyiv City"       "Chernihiv"      
[10] "Crimea"          "Chernivtsi"      "Ivano-Frankivsk" "Khmelnytskyi"    "Lviv"            "Mykolaiv"        "Odesa"           "Poltava"         "Vinnytsia"      
[19] "Kirovograd"      "Zhytomyr"        "Ternopil"        "Cherkasy"        "Kyiv"            "Volyn"           NA                "Rivne"           "Zakarpattia"    
unique(conflict$event_type)
[1] "Explosions/Remote violence" "Battles"                    "Strategic developments"     "Violence against civilians" "Protests"                  
[6] "Riots"                     
unique(conflict$sub_event_type)
 [1] "Shelling/artillery/missile attack"   "Armed clash"                         "Air/drone strike"                    "Remote explosive/landmine/IED"      
 [5] "Disrupted weapons use"               "Other"                               "Agreement"                           "Attack"                             
 [9] "Arrests"                             "Change to group/activity"            "Looting/property destruction"        "Non-state actor overtakes territory"
[13] "Abduction/forced disappearance"      "Peaceful protest"                    "Protest with intervention"           "Government regains territory"       
[17] "Sexual violence"                     "Suicide bomb"                        "Grenade"                             "Non-violent transfer of territory"  
[21] "Mob violence"                        "Excessive force against protesters"  "Headquarters or base established"    "Violent demonstration"              

Apparent War Crimes in Northern Ukraine

Heavy Fighting Along the Frontline in Eastern Ukraine

Political Violence in Eastern Ukraine

Eastern Ukraine faces unprecedented violence, with three-quarters of political violence events occurring in the region, primarily due to shelling, artillery, and missile attacks. Despite relative distance from the frontline, the Dnipropetrovsk region remains at risk, as Russia continues air and missile strikes, exemplified by the deadly incident in Dnipro on 14 January 2023.

conflict_eastern_ukraine <- conflict %>%
  dplyr::filter(
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
                admin1 %in% eastern_ukraine_states_names)
event_counts_eastern_ukraine <- conflict_eastern_ukraine %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), event_type)
east_ukraine_states_rds
class       : SpatialPolygonsDataFrame 
features    : 5 
extent      : 32.96244, 40.21807, 46.07875, 50.46491  (xmin, xmax, ymin, ymax)
crs         : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 
variables   : 10
Warning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NA
names       : GID_0,  NAME_0,    GID_1,          NAME_1,                                                                                      VARNAME_1, NL_NAME_1,  TYPE_1, ENGTYPE_1, CC_1, HASC_1 
min values  :   UKR, Ukraine, UKR.15_1, Dnipropetrovs'k,                                                                 Charkow|Jarkov|Karkov|Khar'kov,        NA, Oblast',    Region,   NA,  UA.DP 
max values  :   UKR, Ukraine,  UKR.8_1,    Zaporizhzhya, Saporoshje|Zaporizhia|Zaporiz'ka Oblast'|Zaporojie|Zaporozhskaya Oblast'|Zaporozh'ye|Zaporožje,        NA, Oblast',    Region,   NA,  UA.ZP 
eastern_ukraine_map <- ggplot() +
  geom_polygon(data=east_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
eastern_ukraine_map

centroid <- east_ukraine_states_rds$centroid <- coordinates(east_ukraine_states_rds)
centroid[2] = centroid[2]+0.4
centroid[7] = centroid[7]-0.4
centroid[3] = centroid[3]-0.4
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = c("Dnipropetrovsk", "Donetsk", "Kharkiv", "Luhansk", "Zaporizhia")), color = "black", size = 4)
eastern_ukraine_map +
  geom_point(data = event_counts_eastern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
  geom_point(color="black", shape=21, data = event_counts_eastern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
  scale_size_continuous(range = c(0.1, 5)) +
  labs(color = "Event Type", size = "Number of Events") +
  labs(title = "Political Violence in Eastern Ukraine", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5)) +
  text

Conflict in Kharkiv

Although Russian forces were unable to break Ukrainian defenses around the city of Kharkiv, they had occupied the bulk of the region’s northern and eastern parts by April 2022, including Izium – a critical transport hub Ukraine liberated almost the entire region in a surprise counter-offensive in September 2022. Of over 800 events targeting civilians, about three-quarters constituted artillery, missile, and airstrike events, which also resulted in the majority of reported civilian fatalities recorded in the region. About a third of these occurred in March 2022 alone.

conflict_kharkiv <- conflict %>%
  dplyr::filter(
                civilian_targeting != "",
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                admin1 == "Kharkiv")
# Create a new column called 'new_event_type'
conflict_kharkiv$new_event_type <- NA

# Map values based on 'sub_event_type'
conflict_kharkiv$new_event_type[conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack")] <- conflict_kharkiv$sub_event_type[conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack")]
conflict_kharkiv$new_event_type[!(conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack"))] <- "Other violence"
number_of_events_kharkiv <- conflict_kharkiv %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), new_event_type)
kharkiv <- subset(ukraine_states_rds, NAME_1 == "Kharkiv")
kharkiv_map <- ggplot() +
  geom_polygon(data=kharkiv,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
kharkiv_map

kharkiv_map +
  geom_point(data = number_of_events_kharkiv, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_kharkiv, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Sub-Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Kharkiv", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Luhansk

The sheer scale of artillery, missile, and air attacks inflicted on Luhansk region as well as intense close combat brought about immense suffering for the civilians. On 11 March 2022, 56 elderly patients reportedly died during the shelling of a nursing home in Kreminna, and at least 60 people were killed in an airstrike on a school used as a shelter in Bilohorivka on 7 May 2022. Over 50 civilians were also killed during the shelling of Severodonetsk in March and May 2022. Following the Russian occupation of the region in summer 2022, the number of reports of civilians being targeted went sharply down; though the region has remained highly kinetic, especially since autumn.

conflict_luhansk <- conflict %>%
  dplyr::filter(
                civilian_targeting != "",
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                admin1 == "Luhansk")
# Create a new column called 'new_event_type'
conflict_luhansk$new_event_type <- NA

# Map values based on 'sub_event_type'
conflict_luhansk$new_event_type[conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack")] <- conflict_luhansk$sub_event_type[conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack")]
conflict_luhansk$new_event_type[!(conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack"))] <- "Other violence"
number_of_events_luhansk <- conflict_luhansk %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), new_event_type)
luhansk <- subset(ukraine_states_rds, NAME_1 == "Luhans'k")
luhansk_map <- ggplot() +
  geom_polygon(data=luhansk,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
luhansk_map

luhansk_map +
  geom_point(data = number_of_events_luhansk, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_luhansk, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Sub-Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Luhansk", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Donetsk

ACLED records over 16,000 events in Donetsk region, of which over 12,000 were attributed to shelling, artillery, missile, and airstrike events. Only a small portion of these events – about 800 – could be attributed to the direct targeting of civilian. The city of Mariupol was the site of several mass casualty events ahead of the Russian occupation. Mass casualty events due to long-range missile and artillery strikes occurred in other parts of the region and on both sides of the line of contact.

conflict_donetsk <- conflict %>%
  dplyr::filter(
                civilian_targeting != "",
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                admin1 == "Donetsk")
# Create a new column called 'new_event_type'
conflict_donetsk$new_event_type <- NA

# Map values based on 'sub_event_type'
conflict_donetsk$new_event_type[conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_donetsk$sub_event_type[conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_donetsk$new_event_type[!(conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_donetsk <- conflict_donetsk %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), new_event_type)
donetsk <- subset(ukraine_states_rds, NAME_1 == "Donets'k")
donetsk_map <- ggplot() +
  geom_polygon(data=donetsk,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
donetsk_map

donetsk_map +
  geom_point(data = number_of_events_donetsk, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_donetsk, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Sub-Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Donetsk", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Zaporizhia

Russian forces occupied most of the Zaporizhia region in the first weeks of the invasion, capturing the entire shore of the Sea of Azov, including the Ukrainian navy base in Berdiansk, and an area stretching between the Kherson and southern Donetsk regions up to the Dnipro river, including the second-largest town of Melitopol. Ukrainian forces stopped Russian forces in the area of Orikhiv and Huliaipole Although shelling and air and drone strikes have accounted for about half of events targeting civilians in the Zaporizhia region, civilians have also been the subject of direct attacks. These include firing at vehicles carrying evacuating civilians, as well as torture and execution. In areas under Russian occupation, reports of the abduction of local officials, teachers, journalists, Ukrainian army veterans, and civil activists are common.

conflict_zaporizhia <- conflict %>%
  dplyr::filter(
                civilian_targeting != "",
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                admin1 == "Zaporizhia")
# Create a new column called 'new_event_type'
conflict_zaporizhia$new_event_type <- NA

# Map values based on 'sub_event_type'
conflict_zaporizhia$new_event_type[conflict_zaporizhia$sub_event_type %in% c("Attack", "Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_zaporizhia$sub_event_type[conflict_zaporizhia$sub_event_type %in% c("Attack","Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_zaporizhia$new_event_type[!(conflict_zaporizhia$sub_event_type %in% c("Attack","Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_zaporizhia <- conflict_zaporizhia %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), new_event_type)
zaporizhia <- subset(ukraine_states_rds, NAME_1 == "Zaporizhzhya")
zaporizhia_map <- ggplot() +
  geom_polygon(data=zaporizhia,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
zaporizhia_map

zaporizhia_map +
  geom_point(data = number_of_events_zaporizhia, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_zaporizhia, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Sub-Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Zaporizhia", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Explosive Threats for Civilians in Southern Ukraine

Russian attempts for landings from the Black Sea were unsuccessful. Russian forces invaded southern Ukraine from the annexed Crimean peninsula, successfully overtaking the Kherson region and its main city in March 2022. The Kherson and Mykolaiv regions experienced significant violence, with artillery strikes leading to high fatality numbers. The most common types of violence in Kherson were abductions, forced disappearances, torture, targeting primarily officials, journalists, activists, and those suspected of pro-Ukrainian views. In June 2022, Russian forces reportedly abducted about 50 Crimean Tatars from Kherson. Two significant incidents in the Odesa region include a missile strike that killed 8 and injured 10 civilians on April 2022, and an airstrike that killed at least 21 civilians on July 2022.

southern_ukraine_states_name = c("Mykolaiv", "Kherson", "Crimea", "Odesa" )
conflict_southern_ukraine <- conflict %>%
  dplyr::filter(
                civilian_targeting != "",
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                admin1 %in% southern_ukraine_states_name)
# Create a new column called 'new_event_type'
conflict_southern_ukraine$new_event_type <- NA

# Map values based on 'sub_event_type'
conflict_southern_ukraine$new_event_type[conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_southern_ukraine$sub_event_type[conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_southern_ukraine$new_event_type[!(conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_southern_ukraine <- conflict_southern_ukraine %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), new_event_type)
southern_ukraine <- subset(ukraine_states_rds, NAME_1 %in% southern_ukraine_states_rds_names)
southern_ukraine_map <- ggplot() +
  geom_polygon(data=southern_ukraine,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
southern_ukraine_map

southern_ukraine_map +
  geom_point(data = number_of_events_southern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_southern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Sub-Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Southern Ukraine", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Constant Menace from the Skies in Central and Western Ukraine

Over 150 Russian missile, air, and drone strikes have targeted the Central and West regions, posing a significant threat to civilian safety. Approximately one-fifth of these strikes hit civilian areas, leading to over 80 fatalities. Two incidents accounted for most of the reported fatalities: a missile strike on a shopping mall, in Poltava, on June 2022, and a missile strike on a Vinnytsia concert hall on July 2022. At least 50 Russian strikes targeted energy infrastructure deep within Ukraine which caused power outages, with Vinnytsia being one of the most affected regions.

unique(conflict$admin1)
 [1] "Dnipropetrovsk"  "Luhansk"         "Donetsk"         "Kharkiv"         "Kherson"         "Sumy"            "Zaporizhia"      "Kyiv City"       "Chernihiv"      
[10] "Crimea"          "Chernivtsi"      "Ivano-Frankivsk" "Khmelnytskyi"    "Lviv"            "Mykolaiv"        "Odesa"           "Poltava"         "Vinnytsia"      
[19] "Kirovograd"      "Zhytomyr"        "Ternopil"        "Cherkasy"        "Kyiv"            "Volyn"           NA                "Rivne"           "Zakarpattia"    
central_western_ukraine_states_name <-  c("Volyn", "Rivne", "Lviv", "Ternopil", "Khmelnytskyi", "Ivano-Frankivsk", "Zakarpattia", "Chernivtsi", "Vinnytsia", "Cherkasy", "Kirovograd", "Poltava" )

conflict_central_western_ukraine <- conflict %>%
  dplyr::filter(
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                sub_event_type == "Shelling/artillery/missile attack",
                admin1 %in% central_western_ukraine_states_name
                )
number_of_events_central_western_ukraine <- conflict_central_western_ukraine %>%
  group_by(latitude, longitude) %>%
  summarize(number_of_events = n(), .groups = "drop")
central_western_ukraine <- subset(ukraine_states_rds, NAME_1 %in% central_ukraine_states_rds_names | NAME_1 %in% western_ukraine_states_rds_names)
central_western_ukraine_map <- ggplot() +
  geom_polygon(data=central_western_ukraine,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
central_western_ukraine_map

central_western_ukraine_map +
  geom_point(color="black", shape=21, fill="darkblue", alpha=0.6, data = number_of_events_central_western_ukraine, aes(x = longitude, y = latitude, size = number_of_events)) +
  scale_size_continuous(range = c(1, 10), guide = 'legend', breaks = c(1, 10, 20, 50), labels = c("1", "10", "20", "50+")) +
  labs(size = "Number of Events") +
  labs(title = "Long-Range Strikes in Central and Western Ukraine", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Interactive Map

library(leaflet)
ukraine_interactive_map <- leaflet() %>%
  addTiles() %>%
  setView(lng = 37.7933, lat = 48.1450, zoom = 7)
ukraine_interactive_map
eastern_ukraine_states_names = list("Dnipropetrovsk", "Luhansk", "Donetsk", "Kharkiv", "Zaporizhia")
conflict_eastern_ukraine <- conflict %>%
  dplyr::filter(
                event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
                event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
                admin1 %in% eastern_ukraine_states_names)
events <- data.frame(latitude = conflict_eastern_ukraine$latitude,
                     longitude = conflict_eastern_ukraine$longitude)
m <- ukraine_interactive_map %>%
  addCircleMarkers(data = events,
                   lng = ~longitude,
                   lat = ~latitude,
                   radius = 1,
                   color = "red",
                   fill = TRUE,
                   fillOpacity = 0.8)

# Display the map
m
m2 <- addPolygons(
  map = m,
  data = east_ukraine_states_rds,
  fillColor = "orange",
  fillOpacity = 0.2,
  color = "black",
  weight = 1
)
m2

Pre-Invasion

The Euromaidan protests, which started in late 2013, were primarily centered in the capital city of Kyiv (Kiev) but spread to other regions as well. The protests involved clashes between demonstrators and law enforcement, resulting in instances of violence, injuries, and fatalities.

Before the Russian invasion the violence in eastern Ukraine was already concentrated in areas close to the Ukrainian-Russian border, particularly in the Donetsk and Luhansk regions. Cities such as Donetsk, Luhansk, Mariupol, and Sloviansk witnessed intense fighting and became hotspots of violence.

Both sides of the conflict engaged in military operations, including artillery shelling, sniper attacks, and armed clashes. The violence was not limited to specific cities but was spread across the conflict-affected regions.

The conflict resulted in a significant number of civilian casualties and widespread displacement of residents. Civilians, including those living in towns and villages near the front lines, faced the risk of violence and were often caught in the crossfire.

ukraine_map2

centroid <- ukraine_states_rds$centroid <- coordinates(ukraine_states_rds)
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds$NAME_1), color = "black", size = 4)
pi_ukraine_map <- ukraine_map2 + 
  geom_text(aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds_names), size=2) + labs(title = "Pre-Invasion Conflicts", fontface="bold") + theme_void() + theme(plot.title = element_text(hjust = 0.5, face = "bold")) +  coord_map(projection = "albers", lat0 = 49, lat1 = 54)
pi_ukraine_map

conflict_pi_ukraine <- conflict %>%
  dplyr::filter(
                event_date <= as.Date("2022-02-01"),
                 civilian_targeting != ""
                )
number_of_events_pi_ukraine <- conflict_pi_ukraine %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), event_type)
pi_ukraine_map +
  geom_point(data = number_of_events_pi_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
  geom_point(color="black", shape=21, data = number_of_events_pi_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
  scale_size_continuous(range = c(0.1, 10)) +
  labs(color = "Event Type", size = "Number of Events") +
  labs(title = "Violence targeting Civilians in Pre-Invasion Ukraine", fontface="bold") + 
  labs(subtitle = "Before February 2022 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Political Violence in Eastern Ukraine Pre-Invasion

conflict_eastern_ukraine_pi <- conflict %>%
  dplyr::filter(
                disorder_type == "Political violence",
                event_date < as.Date("2022-02-01"),
                event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
                admin1 %in% eastern_ukraine_states_names)
event_counts_eastern_ukraine_pi <- conflict_eastern_ukraine_pi %>%
  group_by(longitude, latitude) %>%
  reframe(number_of_events = n(), event_type)
eastern_ukraine_map <- ggplot() +
  geom_polygon(data=east_ukraine_states_rds,  aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
eastern_ukraine_map

centroid <- east_ukraine_states_rds$centroid <- coordinates(east_ukraine_states_rds)
centroid[2] = centroid[2]+0.4
centroid[7] = centroid[7]-0.4
centroid[3] = centroid[3]-0.4
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = c("Dnipropetrovsk", "Donetsk", "Kharkiv", "Luhansk", "Zaporizhia")), color = "black", size = 4)
eastern_ukraine_map +
  geom_point(data = event_counts_eastern_ukraine_pi, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
  geom_point(color="black", shape=21, data = event_counts_eastern_ukraine_pi, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
  scale_size_continuous(range = c(0.1, 5)) +
  labs(color = "Event Type", size = "Number of Events") +
  labs(title = "Political Violence in Eastern Ukraine Pre-Invasion", fontface="bold") + 
  labs(subtitle = "February 2022 - January 2023 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5)) +
  text

conflict_ukraine_pi_riots <- conflict %>%
  dplyr::filter(
                disorder_type == "Political violence",
                event_date < as.Date("2022-02-01"),
                event_type == "Riots"
                )
ukraine_map2 +
  geom_point(color="black", shape=21, fill="orange", alpha=0.6, data = conflict_ukraine_pi_riots, aes(x = longitude, y = latitude, size = 1)) +
  labs(title = "Riots in Pre-Invasion Ukraine", fontface="bold") + 
  labs(subtitle = "Before February 2022 ") +
  coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
  guides(size = "none") +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

LS0tCmF1dGhvcjogIkVsaWYgw4dheXNhciwgR2lyYXkgQ2/Fn2t1biwgU3VkZSBCdWtldCBLaXByaSwgWmV5bmVwIEFrYW50Igp0aXRsZTogIkVjb24gNDk0IFNwYXRpYWwgRGF0YSBTY2llbmNlIFByb2plY3QgLSBBbmFseXNpcyBvZiBBQ0xFRCBSZXBvcnQgV2FyIGluIFVrcmFpbmUiCm91dHB1dDogaHRtbF9ub3RlYm9vawppbnN0aXR1dGU6ICJTYWJhbmNpIFVuaXZlcnNpdHkiCmZvcm1hdDoKICBwZGY6IGRlZmF1bHQKZWRpdG9yOiB2aXN1YWwKLS0tCgojIEVDT04gNDk0IC0gU3BhdGlhbCBEYXRhIFNjaWVuY2UgUHJvamVjdAoKT3VyIHByb2plY3QgYWltZWQgdG8gYW5hbHl6ZSB0aGUgVWtyYWluZSBjb25mbGljdCB1c2luZyBzcGF0aWFsIGFuYWx5c2lzIGFuZCBtYXBzIGdlbmVyYXRlZCB0aHJvdWdoIGRhdGEgZnJvbSBBQ0xFRCAoQXJtZWQgQ29uZmxpY3QgTG9jYXRpb24gJiBFdmVudCBEYXRhIFByb2plY3QpLiBGb2N1c2luZyBvbiB0aGUgdmlvbGVuY2UgdGFyZ2V0aW5nIGNpdmlsaWFucyBhZnRlciBpbnZhc2lvbiBvZiBSdXNzaWEgaW50byBVa3JhaW5lLCB3ZSB1dGlsaXplZCBSIHByb2dyYW1taW5nIHRvIGV4dHJhY3QgYW5kIHZpc3VhbGl6ZSB0aGUgY29uZmxpY3QgZGF0YSwgZW5hYmxpbmcgdXMgdG8gcHJlc2VudCBhIGNvbXByZWhlbnNpdmUgb3ZlcnZpZXcgb2YgdGhlIGV2ZW50cyBhbmQgdGhlaXIgc3BhdGlhbCBkaXN0cmlidXRpb24uCgpgYGB7cn0KbGlicmFyeShzcCkKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY29uZmxpY3RlZCkKYGBgCgojIyBJbnRyb2R1Y3Rpb24KCi0gICBSdXNzaWEgaW52YWRlZCBVa3JhaW5lIGluIEZlYnJ1YXJ5IDIwMjIsIHJlc3VsdGluZyBpbiB0aGUgaGlnaGVzdCBsZXZlbHMgb2YgcG9saXRpY2FsIHZpb2xlbmNlIHJlY29yZGVkIGluIGEgc2luZ2xlIGNvdW50cnkgYnkgQUNMRUQuCgotICAgQ2l2aWxpYW5zIGluIFVrcmFpbmUgaGF2ZSBmYWNlZCBzaGVsbGluZywgaW5kaXNjcmltaW5hdGUgc3RyaWtlcywgZGVsaWJlcmF0ZSBhdHRhY2tzLCBhbmQgaGFyc2ggdHJlYXRtZW50IGluIG9jY3VwaWVkIGFyZWFzLgoKLSAgIFJ1c3NpYW4gZm9yY2VzIHRhcmdldGVkIEt5aXYgYnV0IHJldHJlYXRlZCBpbiBub3J0aGVybiBVa3JhaW5lIHdoaWxlIHF1aWNrbHkgc2VpemluZyB0ZXJyaXRvcmllcyBpbiBzb3V0aGVybiBhbmQgZWFzdGVybiByZWdpb25zLgoKLSAgIE92ZXIgNSwwMDAgcmVwb3J0ZWQgY2l2aWxpYW4gZmF0YWxpdGllcyBoYXZlIG9jY3VycmVkLCBidXQgdGhlIGFjdHVhbCB0b2xsIGlzIGxpa2VseSBtdWNoIGhpZ2hlci4KCi0gICBEaWZmZXJlbnQgcmVnaW9ucyBvZiBVa3JhaW5lIGV4cGVyaWVuY2VkIHZhcnlpbmcgbGV2ZWxzIG9mIHZpb2xlbmNlIGFuZCBvY2N1cGF0aW9uIGR1cmluZyB0aGUgY29uZmxpY3QuCgpgYGB7cn0KI3VrcmFpbmVfc3RhdGVzX3JkcyA8LSByYXN0ZXI6OmdldERhdGEoJ0dBRE0nLCBjb3VudHJ5ID0gIlVLUiIsIGxldmVsID0gMSkKdWtyYWluZV9zdGF0ZXNfcmRzID0gcmVhZFJEUygidWtyYWluZS5yZHMiKSAjaHR0cHM6Ly9nYWRtLm9yZy9kb3dubG9hZF9jb3VudHJ5Lmh0bWwKYGBgCgpgYGB7cn0KdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXVrcmFpbmVfc3RhdGVzX3JkcywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGlkKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGEgPSAwLjYgKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKQp1a3JhaW5lX21hcApgYGAKCmBgYHtyfQplYXN0X3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJEbmlwcm9wZXRyb3ZzJ2siLCAiRG9uZXRzJ2siLCAiTHVoYW5zJ2siICwgICJLaGFya2l2IiwgIlphcG9yaXpoemh5YSIpCgplYXN0X3VrcmFpbmVfc3RhdGVzX3JkcyA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgJWluJSBlYXN0X3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKYGBgCgpgYGB7cn0Kc291dGhfdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzIDwtIGxpc3QoIkNoZXJuaWhpdiIsICJLaWV2IiwgIktpZXYgQ2l0eSIsICJaaHl0b215ciIsICJTdW15IikKc291dGhfdWtyYWluZV9zdGF0ZXNfcmRzIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIHNvdXRoX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKYGBgCgpgYGB7cn0KY2VudHJhbF91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMgPC0gbGlzdCgiQ2hlcmthc3kiLCAiS2lyb3ZvaHJhZCIsICJQb2x0YXZhIiwgIlZpbm55dHN5YSIpCmNlbnRyYWxfdWtyYWluZV9zdGF0ZXNfcmRzIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIGNlbnRyYWxfdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzKQpgYGAKCmBgYHtyfQp3ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJWb2x5biIsICJDaGVybml2dHNpIiwgIkl2YW5vLUZyYW5raXZzJ2siLCAiS2htZWwnbnl0cydreXkiLCAiUml2bmUiLCAiTCd2aXYiLCAiVGVybm9waWwnIiwgIlRyYW5zY2FycGF0aGlhIikKd2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHMgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xICVpbiUgd2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMpCmBgYAoKYGBge3J9CnNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJDcmltZWEiLCAiS2hlcnNvbiIsICAiTXlrb2xheWl2IiwgIk9kZXNzYSIpCnNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3JkcyA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgJWluJSBzb3V0aGVybl91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMpCmBgYAoKYGBge3J9CnVrcmFpbmVfbWFwMiA8LSB1a3JhaW5lX21hcCArIAogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0icmVkIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9c291dGhfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0iYmxhY2siLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsKICBnZW9tX3BvbHlnb24oZGF0YT1jZW50cmFsX3VrcmFpbmVfc3RhdGVzX3JkcywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9ImRhcmtibHVlIiwgYWxwaGE9MC40LCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9d2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHMsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJsaWdodGJsdWUiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsKICBnZW9tX3BvbHlnb24oZGF0YT1zb3V0aGVybl91a3JhaW5lX3N0YXRlc19yZHMsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpCgp1a3JhaW5lX21hcDIKYGBgCgpgYGB7cn0KY2VudHJvaWQgPC0gdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKHVrcmFpbmVfc3RhdGVzX3JkcykKdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzIDwtIHVrcmFpbmVfc3RhdGVzX3JkcyROQU1FXzEKYGBgCgpgYGB7cn0KdWtyYWluZV9tYXAzIDwtIHVrcmFpbmVfbWFwMiArIAogIGdlb21fdGV4dChhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IHVrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyksIHNpemU9MikgKyBsYWJzKHRpdGxlID0gIlJlZ2lvbnMgb2YgVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSkgKyAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpCnVrcmFpbmVfbWFwMwpgYGAKCiMjIENvbmZsaWN0IERhdGEgKEFDTEVEKQoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMgPSBsaXN0KCJEbmlwcm9wZXRyb3ZzayIsICJMdWhhbnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJaYXBvcml6aGlhIikKYGBgCgpgYGB7cn0KY29uZmxpY3QgPC0gcmVhZF9jc3YoJ3VrcmFpbmUuY3N2Jywgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKY29uZmxpY3QkZXZlbnRfZGF0ZSA8LSBhcy5EYXRlKGNvbmZsaWN0JGV2ZW50X2RhdGUsIGZvcm1hdCA9ICIlZCAlQiAlWSIpCmBgYAoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRhZG1pbjEpCmBgYAoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRldmVudF90eXBlKQpgYGAKCmBgYHtyfQp1bmlxdWUoY29uZmxpY3Qkc3ViX2V2ZW50X3R5cGUpCmBgYAoKIyMgQXBwYXJlbnQgV2FyIENyaW1lcyBpbiBOb3J0aGVybiBVa3JhaW5lCgojIyBIZWF2eSBGaWdodGluZyBBbG9uZyB0aGUgRnJvbnRsaW5lIGluIEVhc3Rlcm4gVWtyYWluZQoKIyMjIFBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUKCkVhc3Rlcm4gVWtyYWluZSBmYWNlcyB1bnByZWNlZGVudGVkIHZpb2xlbmNlLCB3aXRoIHRocmVlLXF1YXJ0ZXJzIG9mIHBvbGl0aWNhbCB2aW9sZW5jZSBldmVudHMgb2NjdXJyaW5nIGluIHRoZSByZWdpb24sIHByaW1hcmlseSBkdWUgdG8gc2hlbGxpbmcsIGFydGlsbGVyeSwgYW5kIG1pc3NpbGUgYXR0YWNrcy4KRGVzcGl0ZSByZWxhdGl2ZSBkaXN0YW5jZSBmcm9tIHRoZSBmcm9udGxpbmUsIHRoZSBEbmlwcm9wZXRyb3ZzayByZWdpb24gcmVtYWlucyBhdCByaXNrLCBhcyBSdXNzaWEgY29udGludWVzIGFpciBhbmQgbWlzc2lsZSBzdHJpa2VzLCBleGVtcGxpZmllZCBieSB0aGUgZGVhZGx5IGluY2lkZW50IGluIERuaXBybyBvbiAxNCBKYW51YXJ5IDIwMjMuCgoKYGBge3J9CmNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgJWluJSBjKCJFeHBsb3Npb25zL1JlbW90ZSB2aW9sZW5jZSIsICJCYXR0bGVzIiwgIlZpb2xlbmNlIGFnYWluc3QgY2l2aWxpYW5zIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBlYXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWVzKQpgYGAKCmBgYHtyfQpldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lIDwtIGNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKSArIHRoZW1lX3ZvaWQoKQplYXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyb2lkIDwtIGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzKQpjZW50cm9pZFsyXSA9IGNlbnRyb2lkWzJdKzAuNApjZW50cm9pZFs3XSA9IGNlbnRyb2lkWzddLTAuNApjZW50cm9pZFszXSA9IGNlbnRyb2lkWzNdLTAuNAp0ZXh0IDwtIGdlb21fdGV4dChkYXRhID0gLCBhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IGMoIkRuaXByb3BldHJvdnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJMdWhhbnNrIiwgIlphcG9yaXpoaWEiKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IGV2ZW50X2NvdW50c19lYXN0ZXJuX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCA1KSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJGZWJydWFyeSAyMDIyIC0gSmFudWFyeSAyMDIzICIpICsKICBjb29yZF9tYXAocHJvamVjdGlvbiA9ICJhbGJlcnMiLCBsYXQwID0gNDksIGxhdDEgPSA1NCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogIHRleHQKYGBgCgojIyMgQ29uZmxpY3QgaW4gS2hhcmtpdgoKQWx0aG91Z2ggUnVzc2lhbiBmb3JjZXMgd2VyZSB1bmFibGUgdG8gYnJlYWsgVWtyYWluaWFuIGRlZmVuc2VzIGFyb3VuZCB0aGUgY2l0eSBvZiBLaGFya2l2LCB0aGV5IGhhZCBvY2N1cGllZCB0aGUgYnVsayBvZiB0aGUgcmVnaW9u4oCZcyBub3J0aGVybiBhbmQgZWFzdGVybiBwYXJ0cyBieSBBcHJpbCAyMDIyLCBpbmNsdWRpbmcgSXppdW0g4oCTIGEgY3JpdGljYWwgdHJhbnNwb3J0IGh1YgpVa3JhaW5lIGxpYmVyYXRlZCBhbG1vc3QgdGhlIGVudGlyZSByZWdpb24gaW4gYSBzdXJwcmlzZSBjb3VudGVyLW9mZmVuc2l2ZSBpbiBTZXB0ZW1iZXIgMjAyMi4KT2Ygb3ZlciA4MDAgZXZlbnRzIHRhcmdldGluZyBjaXZpbGlhbnMsIGFib3V0IHRocmVlLXF1YXJ0ZXJzIGNvbnN0aXR1dGVkIGFydGlsbGVyeSwgbWlzc2lsZSwgYW5kIGFpcnN0cmlrZSBldmVudHMsIHdoaWNoIGFsc28gcmVzdWx0ZWQgaW4gdGhlIG1ham9yaXR5IG9mIHJlcG9ydGVkIGNpdmlsaWFuIGZhdGFsaXRpZXMgcmVjb3JkZWQgaW4gdGhlIHJlZ2lvbi4gQWJvdXQgYSB0aGlyZCBvZiB0aGVzZSBvY2N1cnJlZCBpbiBNYXJjaCAyMDIyIGFsb25lLgoKCgpgYGB7cn0KY29uZmxpY3Rfa2hhcmtpdiA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgY2l2aWxpYW5fdGFyZ2V0aW5nICE9ICIiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGFkbWluMSA9PSAiS2hhcmtpdiIpCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBjYWxsZWQgJ25ld19ldmVudF90eXBlJwpjb25mbGljdF9raGFya2l2JG5ld19ldmVudF90eXBlIDwtIE5BCgojIE1hcCB2YWx1ZXMgYmFzZWQgb24gJ3N1Yl9ldmVudF90eXBlJwpjb25mbGljdF9raGFya2l2JG5ld19ldmVudF90eXBlW2NvbmZsaWN0X2toYXJraXYkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIsICJBdHRhY2siKV0gPC0gY29uZmxpY3Rfa2hhcmtpdiRzdWJfZXZlbnRfdHlwZVtjb25mbGljdF9raGFya2l2JHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiLCAiQXR0YWNrIildCmNvbmZsaWN0X2toYXJraXYkbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9raGFya2l2JHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiLCAiQXR0YWNrIikpXSA8LSAiT3RoZXIgdmlvbGVuY2UiCmBgYAoKYGBge3J9Cm51bWJlcl9vZl9ldmVudHNfa2hhcmtpdiA8LSBjb25mbGljdF9raGFya2l2ICU+JQogIGdyb3VwX2J5KGxvbmdpdHVkZSwgbGF0aXR1ZGUpICU+JQogIHJlZnJhbWUobnVtYmVyX29mX2V2ZW50cyA9IG4oKSwgbmV3X2V2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmtoYXJraXYgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xID09ICJLaGFya2l2IikKa2hhcmtpdl9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWtoYXJraXYsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCmtoYXJraXZfbWFwCmBgYAoKYGBge3J9CmtoYXJraXZfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2toYXJraXYsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19raGFya2l2LCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gS2hhcmtpdiIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyMgQ29uZmxpY3QgaW4gTHVoYW5zawoKVGhlIHNoZWVyIHNjYWxlIG9mIGFydGlsbGVyeSwgbWlzc2lsZSwgYW5kIGFpciBhdHRhY2tzIGluZmxpY3RlZCBvbiBMdWhhbnNrIHJlZ2lvbiBhcyB3ZWxsIGFzIGludGVuc2UgY2xvc2UgY29tYmF0IGJyb3VnaHQgYWJvdXQgaW1tZW5zZSBzdWZmZXJpbmcgZm9yIHRoZSBjaXZpbGlhbnMuCk9uIDExIE1hcmNoIDIwMjIsIDU2IGVsZGVybHkgcGF0aWVudHMgcmVwb3J0ZWRseSBkaWVkIGR1cmluZyB0aGUgc2hlbGxpbmcgb2YgYSBudXJzaW5nIGhvbWUgaW4gS3JlbWlubmEsIGFuZCBhdCBsZWFzdCA2MCBwZW9wbGUgd2VyZSBraWxsZWQgaW4gYW4gYWlyc3RyaWtlIG9uIGEgc2Nob29sIHVzZWQgYXMgYSBzaGVsdGVyIGluIEJpbG9ob3JpdmthIG9uIDcgTWF5IDIwMjIuIE92ZXIgNTAgY2l2aWxpYW5zIHdlcmUgYWxzbyBraWxsZWQgZHVyaW5nIHRoZSBzaGVsbGluZyBvZiBTZXZlcm9kb25ldHNrIGluIE1hcmNoIGFuZCBNYXkgMjAyMi4gCkZvbGxvd2luZyB0aGUgUnVzc2lhbiBvY2N1cGF0aW9uIG9mIHRoZSByZWdpb24gaW4gc3VtbWVyIDIwMjIsIHRoZSBudW1iZXIgb2YgcmVwb3J0cyBvZiBjaXZpbGlhbnMgYmVpbmcgdGFyZ2V0ZWQgd2VudCBzaGFycGx5IGRvd247IHRob3VnaCB0aGUgcmVnaW9uIGhhcyByZW1haW5lZCBoaWdobHkga2luZXRpYywgZXNwZWNpYWxseSBzaW5jZSBhdXR1bW4uIAoKCmBgYHtyfQpjb25mbGljdF9sdWhhbnNrIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBjaXZpbGlhbl90YXJnZXRpbmcgIT0gIiIsCiAgICAgICAgICAgICAgICBldmVudF9kYXRlID49IGFzLkRhdGUoIjIwMjItMDItMDEiKSAmIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMy0wMS0zMSIpLAogICAgICAgICAgICAgICAgYWRtaW4xID09ICJMdWhhbnNrIikKYGBgCgpgYGB7cn0KIyBDcmVhdGUgYSBuZXcgY29sdW1uIGNhbGxlZCAnbmV3X2V2ZW50X3R5cGUnCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGUgPC0gTkEKCiMgTWFwIHZhbHVlcyBiYXNlZCBvbiAnc3ViX2V2ZW50X3R5cGUnCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGVbY29uZmxpY3RfbHVoYW5zayRzdWJfZXZlbnRfdHlwZSAlaW4lIGMoIlNoZWxsaW5nL2FydGlsbGVyeS9taXNzaWxlIGF0dGFjayIsICJBaXIvZHJvbmUgc3RyaWtlIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiQXR0YWNrIildIDwtIGNvbmZsaWN0X2x1aGFuc2skc3ViX2V2ZW50X3R5cGVbY29uZmxpY3RfbHVoYW5zayRzdWJfZXZlbnRfdHlwZSAlaW4lIGMoIlNoZWxsaW5nL2FydGlsbGVyeS9taXNzaWxlIGF0dGFjayIsICJBaXIvZHJvbmUgc3RyaWtlIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiQXR0YWNrIildCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9sdWhhbnNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJBdHRhY2siKSldIDwtICJPdGhlciB2aW9sZW5jZSIKYGBgCgpgYGB7cn0KbnVtYmVyX29mX2V2ZW50c19sdWhhbnNrIDwtIGNvbmZsaWN0X2x1aGFuc2sgJT4lCiAgZ3JvdXBfYnkobG9uZ2l0dWRlLCBsYXRpdHVkZSkgJT4lCiAgcmVmcmFtZShudW1iZXJfb2ZfZXZlbnRzID0gbigpLCBuZXdfZXZlbnRfdHlwZSkKYGBgCgpgYGB7cn0KbHVoYW5zayA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgPT0gIkx1aGFucydrIikKbHVoYW5za19tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWx1aGFuc2ssICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCmx1aGFuc2tfbWFwCmBgYAoKYGBge3J9Cmx1aGFuc2tfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2x1aGFuc2ssIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19sdWhhbnNrLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gTHVoYW5zayIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyMgQ29uZmxpY3QgaW4gRG9uZXRzawoKQUNMRUQgcmVjb3JkcyBvdmVyIDE2LDAwMCBldmVudHMgaW4gRG9uZXRzayByZWdpb24sIG9mIHdoaWNoIG92ZXIgMTIsMDAwIHdlcmUgYXR0cmlidXRlZCB0byBzaGVsbGluZywgYXJ0aWxsZXJ5LCBtaXNzaWxlLCBhbmQgYWlyc3RyaWtlIGV2ZW50cy4gT25seSBhIHNtYWxsIHBvcnRpb24gb2YgdGhlc2UgZXZlbnRzIOKAkyBhYm91dCA4MDAg4oCTIGNvdWxkIGJlIGF0dHJpYnV0ZWQgdG8gdGhlIGRpcmVjdCB0YXJnZXRpbmcgb2YgY2l2aWxpYW4uClRoZSBjaXR5IG9mIE1hcml1cG9sIHdhcyB0aGUgc2l0ZSBvZiBzZXZlcmFsIG1hc3MgY2FzdWFsdHkgZXZlbnRzIGFoZWFkIG9mIHRoZSBSdXNzaWFuIG9jY3VwYXRpb24uIApNYXNzIGNhc3VhbHR5IGV2ZW50cyBkdWUgdG8gbG9uZy1yYW5nZSBtaXNzaWxlIGFuZCBhcnRpbGxlcnkgc3RyaWtlcyBvY2N1cnJlZCBpbiBvdGhlciBwYXJ0cyBvZiB0aGUgcmVnaW9uIGFuZCBvbiBib3RoIHNpZGVzIG9mIHRoZSBsaW5lIG9mIGNvbnRhY3QuCgoKYGBge3J9CmNvbmZsaWN0X2RvbmV0c2sgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIiwKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPj0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpICYgZXZlbnRfZGF0ZSA8PSBhcy5EYXRlKCIyMDIzLTAxLTMxIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgPT0gIkRvbmV0c2siKQpgYGAKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkICduZXdfZXZlbnRfdHlwZScKY29uZmxpY3RfZG9uZXRzayRuZXdfZXZlbnRfdHlwZSA8LSBOQQoKIyBNYXAgdmFsdWVzIGJhc2VkIG9uICdzdWJfZXZlbnRfdHlwZScKY29uZmxpY3RfZG9uZXRzayRuZXdfZXZlbnRfdHlwZVtjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpXSA8LSBjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlW2NvbmZsaWN0X2RvbmV0c2skc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJBYmR1Y3Rpb24vZm9yY2VkIGRpc2FwcGVhcmFuY2UiICwgIlJlbW90ZSBleHBsb3NpdmUvbGFuZG1pbmUvSUVEIildCmNvbmZsaWN0X2RvbmV0c2skbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX2RvbmV0c2sgPC0gY29uZmxpY3RfZG9uZXRzayAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQpkb25ldHNrIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSA9PSAiRG9uZXRzJ2siKQpkb25ldHNrX21hcCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9ZG9uZXRzaywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuMiwgY29sb3I9ImJsYWNrIikgKyBndWlkZXMoZmlsbCA9ICJub25lIikgKyB0aGVtZV92b2lkKCkKZG9uZXRza19tYXAKYGBgCgpgYGB7cn0KZG9uZXRza19tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IG51bWJlcl9vZl9ldmVudHNfZG9uZXRzaywgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgc2l6ZSA9IG51bWJlcl9vZl9ldmVudHMsIGNvbG9yPW5ld19ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2RvbmV0c2ssIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBmaWxsPW5ld19ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCAxMCkpICsKICBsYWJzKGNvbG9yID0gIlN1Yi1FdmVudCBUeXBlIiwgc2l6ZSA9ICJOdW1iZXIgb2YgRXZlbnRzIikgKwogIGxhYnModGl0bGUgPSAiVmlvbGVuY2UgdGFyZ2V0aW5nIENpdmlsaWFucyBpbiBEb25ldHNrIiwgZm9udGZhY2U9ImJvbGQiKSArIAogIGxhYnMoc3VidGl0bGUgPSAiRmVicnVhcnkgMjAyMiAtIEphbnVhcnkgMjAyMyAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMjIyBDb25mbGljdCBpbiBaYXBvcml6aGlhCgpSdXNzaWFuIGZvcmNlcyBvY2N1cGllZCBtb3N0IG9mIHRoZSBaYXBvcml6aGlhIHJlZ2lvbiBpbiB0aGUgZmlyc3Qgd2Vla3Mgb2YgdGhlIGludmFzaW9uLCBjYXB0dXJpbmcgdGhlIGVudGlyZSBzaG9yZSBvZiB0aGUgU2VhIG9mIEF6b3YsIGluY2x1ZGluZyB0aGUgVWtyYWluaWFuIG5hdnkgYmFzZSBpbiBCZXJkaWFuc2ssIGFuZCBhbiBhcmVhIHN0cmV0Y2hpbmcgYmV0d2VlbiB0aGUgS2hlcnNvbiBhbmQgc291dGhlcm4gRG9uZXRzayByZWdpb25zIHVwIHRvIHRoZSBEbmlwcm8gcml2ZXIsIGluY2x1ZGluZyB0aGUgc2Vjb25kLWxhcmdlc3QgdG93biBvZiBNZWxpdG9wb2wuClVrcmFpbmlhbiBmb3JjZXMgc3RvcHBlZCBSdXNzaWFuIGZvcmNlcyBpbiB0aGUgYXJlYSBvZiBPcmlraGl2IGFuZCBIdWxpYWlwb2xlCkFsdGhvdWdoIHNoZWxsaW5nIGFuZCBhaXIgYW5kIGRyb25lIHN0cmlrZXMgaGF2ZSBhY2NvdW50ZWQgZm9yIGFib3V0IGhhbGYgb2YgZXZlbnRzIHRhcmdldGluZyBjaXZpbGlhbnMgaW4gdGhlIFphcG9yaXpoaWEgcmVnaW9uLCBjaXZpbGlhbnMgaGF2ZSBhbHNvIGJlZW4gdGhlIHN1YmplY3Qgb2YgZGlyZWN0IGF0dGFja3MuIFRoZXNlIGluY2x1ZGUgZmlyaW5nIGF0IHZlaGljbGVzIGNhcnJ5aW5nIGV2YWN1YXRpbmcgY2l2aWxpYW5zLCBhcyB3ZWxsIGFzIHRvcnR1cmUgYW5kIGV4ZWN1dGlvbi4KSW4gYXJlYXMgdW5kZXIgUnVzc2lhbiBvY2N1cGF0aW9uLCByZXBvcnRzIG9mIHRoZSBhYmR1Y3Rpb24gb2YgbG9jYWwgb2ZmaWNpYWxzLCB0ZWFjaGVycywgam91cm5hbGlzdHMsIFVrcmFpbmlhbiBhcm15IHZldGVyYW5zLCBhbmQgY2l2aWwgYWN0aXZpc3RzIGFyZSBjb21tb24uCgoKCgpgYGB7cn0KY29uZmxpY3RfemFwb3JpemhpYSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgY2l2aWxpYW5fdGFyZ2V0aW5nICE9ICIiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGFkbWluMSA9PSAiWmFwb3JpemhpYSIpCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBjYWxsZWQgJ25ld19ldmVudF90eXBlJwpjb25mbGljdF96YXBvcml6aGlhJG5ld19ldmVudF90eXBlIDwtIE5BCgojIE1hcCB2YWx1ZXMgYmFzZWQgb24gJ3N1Yl9ldmVudF90eXBlJwpjb25mbGljdF96YXBvcml6aGlhJG5ld19ldmVudF90eXBlW2NvbmZsaWN0X3phcG9yaXpoaWEkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCAiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpXSA8LSBjb25mbGljdF96YXBvcml6aGlhJHN1Yl9ldmVudF90eXBlW2NvbmZsaWN0X3phcG9yaXpoaWEkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJBYmR1Y3Rpb24vZm9yY2VkIGRpc2FwcGVhcmFuY2UiICwgIlJlbW90ZSBleHBsb3NpdmUvbGFuZG1pbmUvSUVEIildCmNvbmZsaWN0X3phcG9yaXpoaWEkbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF96YXBvcml6aGlhJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3phcG9yaXpoaWEgPC0gY29uZmxpY3RfemFwb3JpemhpYSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQp6YXBvcml6aGlhIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSA9PSAiWmFwb3Jpemh6aHlhIikKemFwb3JpemhpYV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXphcG9yaXpoaWEsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCnphcG9yaXpoaWFfbWFwCmBgYAoKYGBge3J9CnphcG9yaXpoaWFfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3phcG9yaXpoaWEsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c196YXBvcml6aGlhLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gWmFwb3JpemhpYSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBFeHBsb3NpdmUgVGhyZWF0cyBmb3IgQ2l2aWxpYW5zIGluIFNvdXRoZXJuIFVrcmFpbmUKClJ1c3NpYW4gYXR0ZW1wdHMgZm9yIGxhbmRpbmdzIGZyb20gdGhlIEJsYWNrIFNlYSB3ZXJlIHVuc3VjY2Vzc2Z1bC4KUnVzc2lhbiBmb3JjZXMgaW52YWRlZCBzb3V0aGVybiBVa3JhaW5lIGZyb20gdGhlIGFubmV4ZWQgQ3JpbWVhbiBwZW5pbnN1bGEsIHN1Y2Nlc3NmdWxseSBvdmVydGFraW5nIHRoZSBLaGVyc29uIHJlZ2lvbiBhbmQgaXRzIG1haW4gY2l0eSBpbiBNYXJjaCAyMDIyLgpUaGUgS2hlcnNvbiBhbmQgTXlrb2xhaXYgcmVnaW9ucyBleHBlcmllbmNlZCBzaWduaWZpY2FudCB2aW9sZW5jZSwgd2l0aCBhcnRpbGxlcnkgc3RyaWtlcyBsZWFkaW5nIHRvIGhpZ2ggZmF0YWxpdHkgbnVtYmVycy4KVGhlIG1vc3QgY29tbW9uIHR5cGVzIG9mIHZpb2xlbmNlIGluIEtoZXJzb24gd2VyZSBhYmR1Y3Rpb25zLCBmb3JjZWQgZGlzYXBwZWFyYW5jZXMsIHRvcnR1cmUsIHRhcmdldGluZyBwcmltYXJpbHkgb2ZmaWNpYWxzLCBqb3VybmFsaXN0cywgYWN0aXZpc3RzLCBhbmQgdGhvc2Ugc3VzcGVjdGVkIG9mIHByby1Va3JhaW5pYW4gdmlld3MuCkluIEp1bmUgMjAyMiwgUnVzc2lhbiBmb3JjZXMgcmVwb3J0ZWRseSBhYmR1Y3RlZCBhYm91dCA1MCBDcmltZWFuIFRhdGFycyBmcm9tIEtoZXJzb24uClR3byBzaWduaWZpY2FudCBpbmNpZGVudHMgaW4gdGhlIE9kZXNhIHJlZ2lvbiBpbmNsdWRlIGEgbWlzc2lsZSBzdHJpa2UgdGhhdCBraWxsZWQgOCBhbmQgaW5qdXJlZCAxMCBjaXZpbGlhbnMgb24gQXByaWwgMjAyMiwgYW5kIGFuIGFpcnN0cmlrZSB0aGF0IGtpbGxlZCBhdCBsZWFzdCAyMSBjaXZpbGlhbnMgb24gSnVseSAyMDIyLgoKCgpgYGB7cn0Kc291dGhlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZSA9IGMoIk15a29sYWl2IiwgIktoZXJzb24iLCAiQ3JpbWVhIiwgIk9kZXNhIiApCmNvbmZsaWN0X3NvdXRoZXJuX3VrcmFpbmUgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIiwKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPj0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpICYgZXZlbnRfZGF0ZSA8PSBhcy5EYXRlKCIyMDIzLTAxLTMxIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBzb3V0aGVybl91a3JhaW5lX3N0YXRlc19uYW1lKQpgYGAKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkICduZXdfZXZlbnRfdHlwZScKY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZSA8LSBOQQoKIyBNYXAgdmFsdWVzIGJhc2VkIG9uICdzdWJfZXZlbnRfdHlwZScKY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZVtjb25mbGljdF9zb3V0aGVybl91a3JhaW5lJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiKV0gPC0gY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRzdWJfZXZlbnRfdHlwZVtjb25mbGljdF9zb3V0aGVybl91a3JhaW5lJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiKV0KY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZVshKGNvbmZsaWN0X3NvdXRoZXJuX3VrcmFpbmUkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3NvdXRoZXJuX3VrcmFpbmUgPC0gY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQpzb3V0aGVybl91a3JhaW5lIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIHNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKc291dGhlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXNvdXRoZXJuX3VrcmFpbmUsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCnNvdXRoZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CnNvdXRoZXJuX3VrcmFpbmVfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3NvdXRoZXJuX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19zb3V0aGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gU291dGhlcm4gVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBDb25zdGFudCBNZW5hY2UgZnJvbSB0aGUgU2tpZXMgaW4gQ2VudHJhbCBhbmQgV2VzdGVybiBVa3JhaW5lCgpPdmVyIDE1MCBSdXNzaWFuIG1pc3NpbGUsIGFpciwgYW5kIGRyb25lIHN0cmlrZXMgaGF2ZSB0YXJnZXRlZCB0aGUgQ2VudHJhbCBhbmQgV2VzdCByZWdpb25zLCBwb3NpbmcgYSBzaWduaWZpY2FudCB0aHJlYXQgdG8gY2l2aWxpYW4gc2FmZXR5LgpBcHByb3hpbWF0ZWx5IG9uZS1maWZ0aCBvZiB0aGVzZSBzdHJpa2VzIGhpdCBjaXZpbGlhbiBhcmVhcywgbGVhZGluZyB0byBvdmVyIDgwIGZhdGFsaXRpZXMuClR3byBpbmNpZGVudHMgYWNjb3VudGVkIGZvciBtb3N0IG9mIHRoZSByZXBvcnRlZCBmYXRhbGl0aWVzOiBhIG1pc3NpbGUgc3RyaWtlIG9uIGEgc2hvcHBpbmcgbWFsbCwgaW4gUG9sdGF2YSwgb24gSnVuZSAyMDIyLCBhbmQgYSBtaXNzaWxlIHN0cmlrZSBvbiBhIFZpbm55dHNpYSBjb25jZXJ0IGhhbGwgb24gSnVseSAyMDIyLgpBdCBsZWFzdCA1MCBSdXNzaWFuIHN0cmlrZXMgdGFyZ2V0ZWQgZW5lcmd5IGluZnJhc3RydWN0dXJlIGRlZXAgd2l0aGluIFVrcmFpbmUgd2hpY2ggY2F1c2VkIHBvd2VyIG91dGFnZXMsIHdpdGggVmlubnl0c2lhIGJlaW5nIG9uZSBvZiB0aGUgbW9zdCBhZmZlY3RlZCByZWdpb25zLgoKCgoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRhZG1pbjEpCmBgYAoKYGBge3J9CmNlbnRyYWxfd2VzdGVybl91a3JhaW5lX3N0YXRlc19uYW1lIDwtICBjKCJWb2x5biIsICJSaXZuZSIsICJMdml2IiwgIlRlcm5vcGlsIiwgIktobWVsbnl0c2t5aSIsICJJdmFuby1GcmFua2l2c2siLCAiWmFrYXJwYXR0aWEiLCAiQ2hlcm5pdnRzaSIsICJWaW5ueXRzaWEiLCAiQ2hlcmthc3kiLCAiS2lyb3ZvZ3JhZCIsICJQb2x0YXZhIiApCmBgYAoKYGBge3J9Cgpjb25mbGljdF9jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIHN1Yl9ldmVudF90eXBlID09ICJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLAogICAgICAgICAgICAgICAgYWRtaW4xICVpbiUgY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWUKICAgICAgICAgICAgICAgICkKYGBgCgpgYGB7cn0KbnVtYmVyX29mX2V2ZW50c19jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdF9jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsYXRpdHVkZSwgbG9uZ2l0dWRlKSAlPiUKICBzdW1tYXJpemUobnVtYmVyX29mX2V2ZW50cyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikKYGBgCgpgYGB7cn0KY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmUgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xICVpbiUgY2VudHJhbF91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMgfCBOQU1FXzEgJWluJSB3ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfbWFwIDwtIGdncGxvdCgpICsKICBnZW9tX3BvbHlnb24oZGF0YT1jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSwgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuMiwgY29sb3I9ImJsYWNrIikgKyBndWlkZXMoZmlsbCA9ICJub25lIikgKyB0aGVtZV92b2lkKCkKY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyYWxfd2VzdGVybl91a3JhaW5lX21hcCArCiAgZ2VvbV9wb2ludChjb2xvcj0iYmxhY2siLCBzaGFwZT0yMSwgZmlsbD0iZGFya2JsdWUiLCBhbHBoYT0wLjYsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2NlbnRyYWxfd2VzdGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cykpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDEsIDEwKSwgZ3VpZGUgPSAnbGVnZW5kJywgYnJlYWtzID0gYygxLCAxMCwgMjAsIDUwKSwgbGFiZWxzID0gYygiMSIsICIxMCIsICIyMCIsICI1MCsiKSkgKwogIGxhYnMoc2l6ZSA9ICJOdW1iZXIgb2YgRXZlbnRzIikgKwogIGxhYnModGl0bGUgPSAiTG9uZy1SYW5nZSBTdHJpa2VzIGluIENlbnRyYWwgYW5kIFdlc3Rlcm4gVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBJbnRlcmFjdGl2ZSBNYXAKCmBgYHtyfQpsaWJyYXJ5KGxlYWZsZXQpCmBgYAoKYGBge3J9CnVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwIDwtIGxlYWZsZXQoKSAlPiUKICBhZGRUaWxlcygpICU+JQogIHNldFZpZXcobG5nID0gMzcuNzkzMywgbGF0ID0gNDguMTQ1MCwgem9vbSA9IDcpCnVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMgPSBsaXN0KCJEbmlwcm9wZXRyb3ZzayIsICJMdWhhbnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJaYXBvcml6aGlhIikKY29uZmxpY3RfZWFzdGVybl91a3JhaW5lIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBldmVudF9kYXRlID49IGFzLkRhdGUoIjIwMjItMDItMDEiKSAmIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMy0wMS0zMSIpLAogICAgICAgICAgICAgICAgZXZlbnRfdHlwZSAlaW4lIGMoIkV4cGxvc2lvbnMvUmVtb3RlIHZpb2xlbmNlIiwgIkJhdHRsZXMiLCAiVmlvbGVuY2UgYWdhaW5zdCBjaXZpbGlhbnMiKSwKICAgICAgICAgICAgICAgIGFkbWluMSAlaW4lIGVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMpCmBgYAoKYGBge3J9CmV2ZW50cyA8LSBkYXRhLmZyYW1lKGxhdGl0dWRlID0gY29uZmxpY3RfZWFzdGVybl91a3JhaW5lJGxhdGl0dWRlLAogICAgICAgICAgICAgICAgICAgICBsb25naXR1ZGUgPSBjb25mbGljdF9lYXN0ZXJuX3VrcmFpbmUkbG9uZ2l0dWRlKQpgYGAKCmBgYHtyfQptIDwtIHVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwICU+JQogIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGV2ZW50cywKICAgICAgICAgICAgICAgICAgIGxuZyA9IH5sb25naXR1ZGUsCiAgICAgICAgICAgICAgICAgICBsYXQgPSB+bGF0aXR1ZGUsCiAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjgpCgojIERpc3BsYXkgdGhlIG1hcAptCmBgYAoKYGBge3J9Cm0yIDwtIGFkZFBvbHlnb25zKAogIG1hcCA9IG0sCiAgZGF0YSA9IGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLAogIGZpbGxDb2xvciA9ICJvcmFuZ2UiLAogIGZpbGxPcGFjaXR5ID0gMC4yLAogIGNvbG9yID0gImJsYWNrIiwKICB3ZWlnaHQgPSAxCikKbTIKYGBgCgojIyBQcmUtSW52YXNpb24KClRoZSBFdXJvbWFpZGFuIHByb3Rlc3RzLCB3aGljaCBzdGFydGVkIGluIGxhdGUgMjAxMywgd2VyZSBwcmltYXJpbHkgY2VudGVyZWQgaW4gdGhlIGNhcGl0YWwgY2l0eSBvZiBLeWl2IChLaWV2KSBidXQgc3ByZWFkIHRvIG90aGVyIHJlZ2lvbnMgYXMgd2VsbC4gVGhlIHByb3Rlc3RzIGludm9sdmVkIGNsYXNoZXMgYmV0d2VlbiBkZW1vbnN0cmF0b3JzIGFuZCBsYXcgZW5mb3JjZW1lbnQsIHJlc3VsdGluZyBpbiBpbnN0YW5jZXMgb2YgdmlvbGVuY2UsIGluanVyaWVzLCBhbmQgZmF0YWxpdGllcy4KCkJlZm9yZSB0aGUgUnVzc2lhbiBpbnZhc2lvbiB0aGUgdmlvbGVuY2UgaW4gZWFzdGVybiBVa3JhaW5lIHdhcyBhbHJlYWR5IGNvbmNlbnRyYXRlZCBpbiBhcmVhcyBjbG9zZSB0byB0aGUgVWtyYWluaWFuLVJ1c3NpYW4gYm9yZGVyLCBwYXJ0aWN1bGFybHkgaW4gdGhlIERvbmV0c2sgYW5kIEx1aGFuc2sgcmVnaW9ucy4gQ2l0aWVzIHN1Y2ggYXMgRG9uZXRzaywgTHVoYW5zaywgTWFyaXVwb2wsIGFuZCBTbG92aWFuc2sgd2l0bmVzc2VkIGludGVuc2UgZmlnaHRpbmcgYW5kIGJlY2FtZSBob3RzcG90cyBvZiB2aW9sZW5jZS4KCkJvdGggc2lkZXMgb2YgdGhlIGNvbmZsaWN0IGVuZ2FnZWQgaW4gbWlsaXRhcnkgb3BlcmF0aW9ucywgaW5jbHVkaW5nIGFydGlsbGVyeSBzaGVsbGluZywgc25pcGVyIGF0dGFja3MsIGFuZCBhcm1lZCBjbGFzaGVzLiBUaGUgdmlvbGVuY2Ugd2FzIG5vdCBsaW1pdGVkIHRvIHNwZWNpZmljIGNpdGllcyBidXQgd2FzIHNwcmVhZCBhY3Jvc3MgdGhlIGNvbmZsaWN0LWFmZmVjdGVkIHJlZ2lvbnMuCgpUaGUgY29uZmxpY3QgcmVzdWx0ZWQgaW4gYSBzaWduaWZpY2FudCBudW1iZXIgb2YgY2l2aWxpYW4gY2FzdWFsdGllcyBhbmQgd2lkZXNwcmVhZCBkaXNwbGFjZW1lbnQgb2YgcmVzaWRlbnRzLiBDaXZpbGlhbnMsIGluY2x1ZGluZyB0aG9zZSBsaXZpbmcgaW4gdG93bnMgYW5kIHZpbGxhZ2VzIG5lYXIgdGhlIGZyb250IGxpbmVzLCBmYWNlZCB0aGUgcmlzayBvZiB2aW9sZW5jZSBhbmQgd2VyZSBvZnRlbiBjYXVnaHQgaW4gdGhlIGNyb3NzZmlyZS4KCmBgYHtyfQp1a3JhaW5lX21hcDIKYGBgCgpgYGB7cn0KY2VudHJvaWQgPC0gdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKHVrcmFpbmVfc3RhdGVzX3JkcykKdGV4dCA8LSBnZW9tX3RleHQoZGF0YSA9ICwgYWVzKHggPSBjZW50cm9pZFssIDFdLCB5ID0gY2VudHJvaWRbLCAyXSwgbGFiZWwgPSB1a3JhaW5lX3N0YXRlc19yZHMkTkFNRV8xKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkKYGBgCgpgYGB7cn0KcGlfdWtyYWluZV9tYXAgPC0gdWtyYWluZV9tYXAyICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gY2VudHJvaWRbLCAxXSwgeSA9IGNlbnRyb2lkWywgMl0sIGxhYmVsID0gdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzKSwgc2l6ZT0yKSArIGxhYnModGl0bGUgPSAiUHJlLUludmFzaW9uIENvbmZsaWN0cyIsIGZvbnRmYWNlPSJib2xkIikgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSkgKyAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpCnBpX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNvbmZsaWN0X3BpX3VrcmFpbmUgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpLAogICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIgogICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUgPC0gY29uZmxpY3RfcGlfdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CnBpX3VrcmFpbmVfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBmaWxsPWV2ZW50X3R5cGUpKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjEsIDEwKSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gUHJlLUludmFzaW9uIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJCZWZvcmUgRmVicnVhcnkgMjAyMiAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMjIFBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUgUHJlLUludmFzaW9uCgpgYGB7cn0KY29uZmxpY3RfZWFzdGVybl91a3JhaW5lX3BpIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBkaXNvcmRlcl90eXBlID09ICJQb2xpdGljYWwgdmlvbGVuY2UiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA8IGFzLkRhdGUoIjIwMjItMDItMDEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgJWluJSBjKCJFeHBsb3Npb25zL1JlbW90ZSB2aW9sZW5jZSIsICJCYXR0bGVzIiwgIlZpb2xlbmNlIGFnYWluc3QgY2l2aWxpYW5zIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBlYXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWVzKQpgYGAKCmBgYHtyfQpldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lX3BpIDwtIGNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZV9waSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKSArIHRoZW1lX3ZvaWQoKQplYXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyb2lkIDwtIGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzKQpjZW50cm9pZFsyXSA9IGNlbnRyb2lkWzJdKzAuNApjZW50cm9pZFs3XSA9IGNlbnRyb2lkWzddLTAuNApjZW50cm9pZFszXSA9IGNlbnRyb2lkWzNdLTAuNAp0ZXh0IDwtIGdlb21fdGV4dChkYXRhID0gLCBhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IGMoIkRuaXByb3BldHJvdnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJMdWhhbnNrIiwgIlphcG9yaXpoaWEiKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IGV2ZW50X2NvdW50c19lYXN0ZXJuX3VrcmFpbmVfcGksIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lX3BpLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCA1KSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUgUHJlLUludmFzaW9uIiwgZm9udGZhY2U9ImJvbGQiKSArIAogIGxhYnMoc3VidGl0bGUgPSAiRmVicnVhcnkgMjAyMiAtIEphbnVhcnkgMjAyMyAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgdGV4dApgYGAKCmBgYHtyfQpjb25mbGljdF91a3JhaW5lX3BpX3Jpb3RzIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBkaXNvcmRlcl90eXBlID09ICJQb2xpdGljYWwgdmlvbGVuY2UiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA8IGFzLkRhdGUoIjIwMjItMDItMDEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgPT0gIlJpb3RzIgogICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQp1a3JhaW5lX21hcDIgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuNiwgZGF0YSA9IGNvbmZsaWN0X3VrcmFpbmVfcGlfcmlvdHMsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiUmlvdHMgaW4gUHJlLUludmFzaW9uIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJCZWZvcmUgRmVicnVhcnkgMjAyMiAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICBndWlkZXMoc2l6ZSA9ICJub25lIikgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCg==